#include "InvoicePrinter.h"
#include "Helper.h"

#include <QFile>
#include <QStringRef>

using namespace ecocity;

bool
InvoicePrinter::print( const QString& path_file, const Invoice& invoice )
{
    QFile file( path_file );

    if ( !file.open( QIODevice::WriteOnly ) )
    {
        return false;
    }

    QTextStream out_stream( &file );

    print_header( out_stream, invoice );

    out_stream << "\n";
    out_stream << "\n";

    std::vector< InvoiceItem> items = invoice.items( );

    print_invoice_items( out_stream, items );

    out_stream << "\n";
    out_stream << "\n";

    out_stream << taxes_summary( invoice );

    out_stream << "\n";
    out_stream << "\n";

    out_stream << final_summary( invoice );

    file.close();

    return true;
}

//---------------------------------------------------------------

void
InvoicePrinter::print_header( QTextStream& out_stream, const Invoice& invoice )
{
    out_stream << QString::fromUtf8( "ECOCITY, Productes ecològics i de proximitat" ) << endl;
    out_stream << QString::fromUtf8( "Carmen Martínez" ) << endl;
    out_stream << "info@ecocity.cat" << endl;
    out_stream << "Telf : 691232340" << endl;
    out_stream << "De dill. a div. de 9-13 i de 16-20h" << endl;
    out_stream << "www.ecocity.cat" << "\n";
    out_stream << endl;
    out_stream << endl;
    out_stream << invoice.customer().name() << endl;
    out_stream << invoice.customer().address() << endl;
    out_stream << invoice.customer().nif() << endl;
    out_stream << invoice.customer().phone() << endl;
}

//---------------------------------------------------------------

void
InvoicePrinter::print_invoice_items( QTextStream &out_stream,
                                     const std::vector< InvoiceItem >& items )
{
    for( size_t i = 0; i < items.size(); ++i )
    {
        print_invoice_item( out_stream, items.at( i ) );
    }
}

//---------------------------------------------------------------

void
InvoicePrinter::print_invoice_item( QTextStream &out_stream,
                                    const InvoiceItem& item )
{
    print_invoice_item_description( out_stream, item );

    out_stream << " "
               << QString::number(
                      item.untaxed_cost_without_discount( ), 'f', 2 ).rightJustified( 7, ' ', true )
               << " EUR ";

    print_invoice_item_discount( out_stream, item );

    out_stream << " Total sin IVA = "
               << QString::number(
                      item.untaxed_cost_with_discount( ), 'f', 2 ).rightJustified( 6, ' ', true )
               << " EUR ";

    print_invoice_item_tax_rate( out_stream, item );

    out_stream << " = ";

    out_stream << QString::number(
                      item.total_cost( ), 'f', 2 ).rightJustified( 7, ' ', true )
               << " EUR" << endl;
}

//---------------------------------------------------------------

void
InvoicePrinter::print_invoice_item_description( QTextStream &out_stream,
                                                const InvoiceItem& item )
{
    QString weight_str;
    QTextStream stream( &weight_str );
    float weight = item.weight( );

    if ( weight > 0 )
    {
        stream << QString::number( weight, 'f', 3 ) << "Kg ";
    }

    QString quantity_and_weight;
    QTextStream stream_quantity_weight( &quantity_and_weight );
    stream_quantity_weight << item.quantity( )
                           << "x"
                           << weight_str;

    out_stream << quantity_and_weight.leftJustified( 11, ' ', true )
               << item.product().name( ).leftJustified( 15, ' ', true );
}

//---------------------------------------------------------------

void
InvoicePrinter::print_invoice_item_discount( QTextStream &out_stream,
                                             const InvoiceItem& item )
{
    float discount_rate = item.discount_rate( );
    float total_discount = item.total_discount( );
    QString discount_str;
    if ( discount_rate > 0 && total_discount > 0 )
    {
        discount_str.append( "- " );
        discount_str.append( QString::number( discount_rate, 'f', 2 ) );
        discount_str.append( " % desc" );
        //discount_str.append( " (" );
        //discount_str.append( QString::number( total_discount, 'f', 2 ) );
        //discount_str.append( " EUR) " );
    }
    // Increase number 24 if you want to show discount in EUR
    out_stream << discount_str.rightJustified( 12, ' ', true );
}

//---------------------------------------------------------------

void
InvoicePrinter::print_invoice_item_tax_rate( QTextStream &out_stream,
                                             const InvoiceItem& item )
{
    float taxes = item.taxes_cost( );
    float tax_rate = item.product( ).tax_rate( );

    QString tax_rate_str;
    QTextStream rate_stream( &tax_rate_str );
    rate_stream << "+ "
                << QString::number( tax_rate ).rightJustified( 2, ' ', true )
                << " % IVA ("
                << QString::number( taxes, 'f', 2 ).rightJustified( 6, ' ', true )
                << " EUR)";

    out_stream << tax_rate_str.rightJustified( 23, ' ', true );
}

//---------------------------------------------------------------

QString
InvoicePrinter::taxes_summary( const Invoice &invoice )
{
    QList< int > tax_rates = Helper::get_tax_rates( invoice );

    QMap< int, float > taxes_map = Helper::get_taxes( invoice, tax_rates );

    QMap<int, float>::const_iterator i = taxes_map.constBegin( );

    QString summary;
    QTextStream stream( &summary );

    while ( i != taxes_map.constEnd() )
    {
        stream << "IVA "
               << QString::number( i.key() ).rightJustified( 3, ' ', true )
               << "% ="
               << QString::number( i.value(), 'f', 2 ).rightJustified( 6, ' ', true )
               << " EUR" << endl;
         ++i;
    }

    return summary;
}

//---------------------------------------------------------------

QString
InvoicePrinter::final_summary( const Invoice &invoice )
{
    QString summary;
    QTextStream stream( &summary );

    stream << QString( "Total (sin IVA)" ).leftJustified( 20, ' ', true )
           << QString::number( invoice.cost_without_taxes(), 'f', 2 ).rightJustified( 7, ' ', true )
           << " EUR " << endl;

    stream << QString( "Total IVA ").leftJustified( 20, ' ', true )
           << QString::number( invoice.taxes_cost( ), 'f', 2 ).rightJustified( 7, ' ', true )
           << " EUR " << endl << endl;

    stream << QString( "Total").leftJustified( 20, ' ', true )
           << QString::number( invoice.total_cost( ), 'f', 2 ).rightJustified( 7, ' ', true )
           << " EUR " << endl;

    return summary;
}
